package com.easylive.service.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.easylive.entity.component.EsSearchComponent;
import com.easylive.entity.constants.Constants;
import com.easylive.entity.enums.ResponseCodeEnum;
import com.easylive.entity.enums.SearchOrderTypeEnum;
import com.easylive.entity.enums.UserActionTypeEnum;
import com.easylive.entity.po.UserInfo;
import com.easylive.entity.po.VideoComment;
import com.easylive.entity.po.VideoInfo;
import com.easylive.entity.query.*;
import com.easylive.exception.BusinessException;
import com.easylive.mappers.UserInfoMapper;
import com.easylive.mappers.VideoCommentMapper;
import com.easylive.mappers.VideoInfoMapper;
import org.springframework.stereotype.Service;

import com.easylive.entity.enums.PageSize;
import com.easylive.entity.po.UserAction;
import com.easylive.entity.vo.PaginationResultVO;
import com.easylive.mappers.UserActionMapper;
import com.easylive.service.UserActionService;
import com.easylive.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;


/**
 * 用户行为：评论点赞踩赞，视频点赞，视频收藏，视频投币 业务接口实现
 */
@Service("userActionService")
public class UserActionServiceImpl implements UserActionService {

	@Resource
	private UserActionMapper<UserAction, UserActionQuery> userActionMapper;

	@Resource
	private VideoInfoMapper<VideoInfo, VideoInfoQuery> videoInfoMapper;

	@Resource
	private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;

	@Resource
	private VideoCommentMapper<VideoComment, VideoCommentQuery> videoCommentMapper;

	@Resource
	private EsSearchComponent esSearchComponent;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<UserAction> findListByParam(UserActionQuery param) {
		return this.userActionMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(UserActionQuery param) {
		return this.userActionMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<UserAction> findListByPage(UserActionQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<UserAction> list = this.findListByParam(param);
		PaginationResultVO<UserAction> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(UserAction bean) {
		return this.userActionMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<UserAction> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userActionMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<UserAction> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userActionMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(UserAction bean, UserActionQuery param) {
		StringTools.checkParam(param);
		return this.userActionMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(UserActionQuery param) {
		StringTools.checkParam(param);
		return this.userActionMapper.deleteByParam(param);
	}

	/**
	 * 根据ActionId获取对象
	 */
	@Override
	public UserAction getUserActionByActionId(Integer actionId) {
		return this.userActionMapper.selectByActionId(actionId);
	}

	/**
	 * 根据ActionId修改
	 */
	@Override
	public Integer updateUserActionByActionId(UserAction bean, Integer actionId) {
		return this.userActionMapper.updateByActionId(bean, actionId);
	}

	/**
	 * 根据ActionId删除
	 */
	@Override
	public Integer deleteUserActionByActionId(Integer actionId) {
		return this.userActionMapper.deleteByActionId(actionId);
	}

	/**
	 * 根据VideoIdAndCommentIdAndActionTypeAndUserId获取对象
	 */
	@Override
	public UserAction getUserActionByVideoIdAndCommentIdAndActionTypeAndUserId(String videoId, Integer commentId, Integer actionType, String userId) {
		return this.userActionMapper.selectByVideoIdAndCommentIdAndActionTypeAndUserId(videoId, commentId, actionType, userId);
	}

	/**
	 * 根据VideoIdAndCommentIdAndActionTypeAndUserId修改
	 */
	@Override
	public Integer updateUserActionByVideoIdAndCommentIdAndActionTypeAndUserId(UserAction bean, String videoId, Integer commentId, Integer actionType, String userId) {
		return this.userActionMapper.updateByVideoIdAndCommentIdAndActionTypeAndUserId(bean, videoId, commentId, actionType, userId);
	}

	/**
	 * 根据VideoIdAndCommentIdAndActionTypeAndUserId删除
	 */
	@Override
	public Integer deleteUserActionByVideoIdAndCommentIdAndActionTypeAndUserId(String videoId, Integer commentId, Integer actionType, String userId) {
		return this.userActionMapper.deleteByVideoIdAndCommentIdAndActionTypeAndUserId(videoId, commentId, actionType, userId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveAction(UserAction bean) {
		UserActionTypeEnum userActionType = UserActionTypeEnum.getByType(bean.getActionType());
		VideoInfo videoInfo = videoInfoMapper.selectByVideoId(bean.getVideoId());
		if (ObjectUtils.isEmpty(videoInfo) || ObjectUtils.isEmpty(userActionType)) {
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		bean.setVideoUserId(videoInfo.getUserId());
		// 判断数据库中有没有这个类型的记录，如果有就是点赞，否则就是取消点赞（收藏同）

		UserAction dbAction = userActionMapper.selectByVideoIdAndCommentIdAndActionTypeAndUserId(bean.getVideoId(), bean.getCommentId(), bean.getActionType(), bean.getUserId());
		bean.setActionTime(new Date());

		switch (userActionType) {
			case VIDEO_LIKE:
			case VIDEO_COLLECT:
				// 点赞和收藏的逻辑基本上一样
				if (ObjectUtils.isEmpty(dbAction)) {
					// 新增
					userActionMapper.insert(bean);
				} else {
					// 删除
					userActionMapper.deleteByActionId(dbAction.getActionId());
				}
				// 更新视频信息表中的点赞或收藏数量
				Integer changeCount = ObjectUtils.isEmpty(dbAction) ? Constants.ONE : -Constants.ONE;
				videoInfoMapper.updateCountInfo(videoInfo.getVideoId(), userActionType.getField(), changeCount);
				if (userActionType.equals(UserActionTypeEnum.VIDEO_COLLECT)) {
					// 如果是收藏，需要更新ES中的收藏数量
					esSearchComponent.updateDocCount(videoInfo.getVideoId(), SearchOrderTypeEnum.VIDEO_COLLECT.getField(), changeCount);
				}

				break;
			case VIDEO_COIN:
				/**
				 * 自己不能给自己投币，并且只能投一次，无法取消
				 */
				if (bean.getUserId().equals(videoInfo.getUserId())) {
					throw new BusinessException("不能给自己投币");
				}
				if (!ObjectUtils.isEmpty(dbAction)) {
					throw new BusinessException("只能投一次币");
				}
				// 把自己的币减少，给别人增加币，数量操作需要加锁，先查再更新就会有问题，
				// 减少自己的币
				Integer updateUserCount = userInfoMapper.updateCoinCountInfo(bean.getUserId(), -bean.getActionCount());
				if (updateUserCount == 0) {
					throw new BusinessException("币不足");
				}
				// 增加up主的币
				Integer updateVideoUserCount = userInfoMapper.updateCoinCountInfo(videoInfo.getUserId(), bean.getActionCount());
				if (updateVideoUserCount == 0) {
					throw new BusinessException("投币失败");
				}
				// 新增投币记录
				userActionMapper.insert(bean);
				// 更新视频信息中的投币数量
				videoInfoMapper.updateCountInfo(videoInfo.getVideoId(), userActionType.getField(), bean.getActionCount());
				break;
			case COMMENT_LIKE:
			case COMMENT_HATE:
				/**
				 * 点赞和踩赞是互斥的
				 * 有好几种方式，比如：点击了点赞，然后又点击了点赞，这时需要取消点赞
				 * 点击了点赞，然后点踩赞
				 * 点击了踩赞，然后点踩赞
				 * 点击踩赞，又点击了点赞
				 */
				// 先获取对立面，如果有则删除，比如：点了点赞，那么要查找踩赞的，如果有，就删除
				UserActionTypeEnum oppositeActionType = userActionType == UserActionTypeEnum.COMMENT_LIKE ? UserActionTypeEnum.COMMENT_HATE : userActionType;
				UserAction oppositeAction = userActionMapper.selectByVideoIdAndCommentIdAndActionTypeAndUserId(bean.getVideoId(), bean.getCommentId(), oppositeActionType.getType(), bean.getUserId());
				if (!ObjectUtils.isEmpty(oppositeAction)) {
					userActionMapper.deleteByActionId(oppositeAction.getActionId());
				}
				if (!ObjectUtils.isEmpty(dbAction)) {
					// 如果刚好有这个点赞或者踩赞记录，则删除，否则插入
					userActionMapper.deleteByActionId(dbAction.getActionId());
				} else {
					userActionMapper.insert(bean);
				}

				// 更新videoComment数量
				changeCount = ObjectUtils.isEmpty(dbAction) ? Constants.ONE : -Constants.ONE;
				Integer oppositeCount = -changeCount;
				videoCommentMapper.updateCountInfo(bean.getCommentId(), userActionType.getField(), changeCount,
						oppositeAction == null ? null : oppositeActionType.getField(), oppositeCount);
				break;
		}

	}
}